#ifndef __SC_COMPUTATION_INFO_H__
#define __SC_COMPUTATION_INFO_H__

////////////////////////////////////////////////////////////////////////////////
// Includes
////////////////////////////////////////////////////////////////////////////////

#include <string>
#include <utility>
#include <vector>

#include "SC_LibConfig.h"

////////////////////////////////////////////////////////////////////////////////
// Namespaces
////////////////////////////////////////////////////////////////////////////////

namespace SC {

////////////////////////////////////////////////////////////////////////////////
// Implementation
////////////////////////////////////////////////////////////////////////////////

/**
 *  This class defines system changes between two system states.
 */
class LIBRARY_DECL SCSystemChanges {

	public:
		
		/// Constructor
		SCSystemChanges() {}
		
		/// Create a copy of the given instance
		SCSystemChanges(const SCSystemChanges & inst)
		:	s1_changes(inst.s1_changes), k_changes(inst.k_changes),
			s2_changes(inst.s2_changes),
			super_changes(inst.super_changes), sub_changes(inst.sub_changes)
		{} 
		
		/// Affectation operator
		SCSystemChanges & operator = (const SCSystemChanges & inst) {
			if (this != &inst) {
				this->s1_changes	= inst.s1_changes;
				this->k_changes		= inst.k_changes;
				this->s2_changes	= inst.s2_changes;
				this->super_changes	= inst.super_changes;
				this->sub_changes	= inst.sub_changes;
			}
			return *this;
		}
		
		/// Schemata and kernel changes
		std::vector< std::pair<unsigned int, std::string> >
			s1_changes, k_changes, s2_changes;

		/// Super and sub systems changes
		/// A change is a pair containing:
		///	  - the nature of the change (true if gaining, false if loosing)
		///	  - the subject of the change
		std::vector< std::pair<bool, unsigned int> > super_changes, sub_changes;

};

////////////////////////////////////////////////////////////////////////////////

/**
 *  This class descibes a computation and its changes since the previous one.
 */
class LIBRARY_DECL SComputationInfo {

	public:

		/// Constructor
		SComputationInfo(
			const bool has_computed = false,
			const int scope_idx = -1,
			const int sys1_idx = -1,
			const int ctx_idx = -1,
			const int sys2_idx = -1
		) : has_computed(has_computed), scope_idx(scope_idx),
			sys1_idx(sys1_idx), ctx_idx(ctx_idx), sys2_idx(sys2_idx)
		{}
		
		/// Create a copy of the given instance
		SComputationInfo(const SComputationInfo & inst)
		:	has_computed(inst.has_computed), scope_idx(inst.scope_idx),
			sys1_idx(inst.sys1_idx), ctx_idx(inst.ctx_idx),
			sys2_idx(inst.sys2_idx), sys1_changes(inst.sys1_changes),
			ctx_changes(inst.ctx_changes), sys2_changes(inst.sys2_changes)
		{} 
		
		/// Affectation operator
		SComputationInfo & operator = (const SComputationInfo & inst) {
			if (this != &inst) {
				this->has_computed	= inst.has_computed;
				this->scope_idx		= inst.scope_idx;
				this->sys1_idx		= inst.sys1_idx;
				this->ctx_idx		= inst.ctx_idx;
				this->sys2_idx		= inst.sys2_idx;
				this->sys1_changes	= inst.sys1_changes;
				this->ctx_changes	= inst.ctx_changes;
				this->sys2_changes	= inst.sys2_changes;
			}
			return *this;
		}
		
		/// Computation value: true if it successfully occurred, false otherwise
		bool has_computed;
		
		/// Computation scope
		int scope_idx;
		
		/// System 1 index
		int sys1_idx;
		
		/// Context index
		int ctx_idx;
		
		/// System 2 index
		int sys2_idx;

		/// System 1 changes
		SCSystemChanges sys1_changes;
		
		/// Context changes
		SCSystemChanges ctx_changes;
		
		/// System 2 changes
		SCSystemChanges sys2_changes;

};

////////////////////////////////////////////////////////////////////////////////
// Closing Namespaces
////////////////////////////////////////////////////////////////////////////////

}

////////////////////////////////////////////////////////////////////////////////

#endif
